//
//  Common.swift
//  MixFruit
//
//  Created by remy on 2021/8/22.
//

@_exported import UIKit
@_exported import SwiftUI
@_exported import SpriteKit

public extension String {
    var localized: String {
        return NSLocalizedString(self, comment: "")
    }
    
    func localized(_ comment: String = "") -> String {
        return NSLocalizedString(self, comment: comment)
    }
    
    static func localized(_ key: String, _ comment: String = "") -> String {
        return NSLocalizedString(key, comment: comment)
    }
}

public extension Set {
    func forEachEnumerated(_ body: ((offset: Int, element: Element)) -> Void) {
        enumerated().forEach(body)
    }
}

public extension Dictionary {
    func forEachEnumerated(_ body: ((offset: Int, element: (key: Key, value: Value))) -> Void) {
        enumerated().forEach(body)
    }
}

public extension Array {
    func forEachEnumerated(_ body: ((offset: Int, element: Element)) -> Void) {
        enumerated().forEach(body)
    }
}

public extension Array where Element: Equatable {
    @discardableResult
    mutating func removeAll(item: Element?) -> [Element] {
        guard let item = item else { return self }
        removeAll(where: { $0 == item })
        return self
    }
    
    @discardableResult
    mutating func removeAll(items: [Element]) -> [Element] {
        guard !items.isEmpty else { return self }
        removeAll(where: { items.contains($0) })
        return self
    }
}

public extension ArraySlice {
    func forEachEnumerated(_ body: ((offset: Int, element: Element)) -> Void) {
        enumerated().forEach(body)
    }
}

public extension String {
    func forEachEnumerated(_ body: ((offset: Int, element: Element)) -> Void) {
        enumerated().forEach(body)
    }
}

public extension UIScreen {
    static var size: CGSize {
        return UIScreen.main.bounds.size
    }
    static var width: CGFloat {
        return UIScreen.main.bounds.size.width
    }
    static var height: CGFloat {
        return UIScreen.main.bounds.size.height
    }
    static var center: CGPoint {
        return CGPoint(x: UIScreen.main.bounds.midX, y: UIScreen.main.bounds.midY)
    }
}

public extension UIColor {
    convenience init(_ hexString: String, _ alpha: CGFloat = 1.0) {
        var string = ""
        if hexString.lowercased().hasPrefix("0x") {
            string = hexString.replacingOccurrences(of: "0x", with: "")
        } else if hexString.hasPrefix("#") {
            string = hexString.replacingOccurrences(of: "#", with: "")
        } else {
            string = hexString
        }
        if let hexValue = Int(string, radix: 16) {
            self.init(hexValue, alpha)
        } else {
            self.init(0x000000, alpha)
        }
    }
    
    convenience init(_ hex: Int, _ alpha: CGFloat = 1.0) {
        let red = (hex >> 16) & 0xff
        let green = (hex >> 8) & 0xff
        let blue = hex & 0xff
        self.init(red: CGFloat(red) / 255.0, green: CGFloat(green) / 255.0, blue: CGFloat(blue) / 255.0, alpha: alpha)
    }
}

public extension SKNode {
    var y: CGFloat {
        get { return position.y }
        set { position.y = newValue }
    }
    var x: CGFloat {
        get { return position.x }
        set { position.x = newValue }
    }
}

public extension SKSpriteNode {
    var width: CGFloat {
        get { return size.width }
        set { size.width = newValue }
    }
    var height: CGFloat {
        get { return size.height }
        set { size.height = newValue }
    }
}

public extension UserDefaults {
    subscript(key: String) -> Any? {
        get { return object(forKey: key) }
        set { set(newValue, forKey: key) }
    }
    
    subscript<T>(key: UDSharedKey<T>) -> T? {
        get { return object(forKey: key.rawValue) as? T }
        set { set(newValue, forKey: key.rawValue) }
    }
    
    static func synchronize() {
        UserDefaults.standard.synchronize()
    }
}

public let UDShared = UserDefaults.standard

public class UDSharedKeys: RawRepresentable {
    public typealias RawValue = String

    public var rawValue: String

    public required init(rawValue: String) {
        self.rawValue = rawValue
    }

    public convenience init(_ rawValue: String) {
        self.init(rawValue: rawValue)
    }
}

public final class UDSharedKey<T>: UDSharedKeys {}
